// License Notification
//======================================================
// Copyright (c) 2010 Channel Intelligence Inc.
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// ======================================================




using System;
using System.IO;
using System.Xml;
using System.Xml.Linq;
using System.Collections.Generic;
using CIP4.Common;

#pragma warning disable 1591        // disable missing documentation comments warning
namespace CIP4.RulesEngine
{
    public abstract class BaseActionType
    {
        public static string RuleXmlNS = Globals.cirNS;

        public static BaseActionType Initialize(XElement element, BaseActionType owner)
        {
            if (element.Name == XName.Get("Action", RuleXmlNS))
                return new ActionType(element, owner);
            if (element.Name == XName.Get("ConditionalAction", RuleXmlNS))
                return new ConditionalActionType(element, owner);
            if (element.Name == XName.Get("ActionSequence", RuleXmlNS))
                return new ActionSequenceType(element, owner);
            throw new ArgumentException(string.Format("{0} is not a recognized action type node", element));
        }

        public static ActionUsageEnum ActionUsageEnumFromString(string s)
        {
            if (s == "none")
                return ActionUsageEnum.None;
            if (s == "ItemValidation")
                return ActionUsageEnum.ItemValidation;
            if (s == "ItemSelection")
                return ActionUsageEnum.ItemSelection;
            if (s == "ItemMapping")
                return ActionUsageEnum.ItemMapping;
            if (s == "ItemCreation")
                return ActionUsageEnum.ItemCreation;
            if (s == "ItemConstruction")
                return ActionUsageEnum.ItemConstruction;

            throw new ArgumentException(string.Format("{0} is not a valid action usage", s));
        }

        protected BaseActionType ObjectOwner { get; set; }

        public ActionOriginType? Origin { get; set; }

        public ActionUsageEnum? Usage { get; set; }

        public string Description { get; set; }

        private Dictionary<string, string> m_FormalParameters;

        /// <summary>
        /// This is a list of the input parameter items provided to the 
        /// Action. The parameter name must be a legal VB/Xml element name
        /// and the type must be the fully qualified name (i.e. ExternalID)
        /// for a compound type - currently largely ignored
        /// </summary>
        public Dictionary<string, string> FormalParameters
        {
            get
            {
                if (m_FormalParameters == null)
                    m_FormalParameters = new Dictionary<string, string>();
                return m_FormalParameters;
            }
        }

        protected void XmlForFormalParameters(XmlWriter xwrtr)
        {
            if (FormalParameters.Count > 0)
            {
                xwrtr.WriteStartElement("FormalParameters");
                foreach (KeyValuePair<string, string> parameter in FormalParameters)
                {
                    xwrtr.WriteStartElement("FormalParameter");
                    xwrtr.WriteAttributeString("Name", parameter.Key);
                    xwrtr.WriteValue(parameter.Value);
                    xwrtr.WriteEndElement();
                }
                xwrtr.WriteEndElement();
            }
        }

        protected void InitializeParameters(XElement element)
        {
            XElement paramNode = element.Element(XName.Get("FormalParameters", RuleXmlNS));
            if (paramNode != null)
            {
                foreach (XElement parameterElement in paramNode.Elements())
                {
                    if (parameterElement.Attribute("Name") == null)
                        throw new ArgumentException("The formal paameter must have a Name attribute");
// ReSharper disable PossibleNullReferenceException
                    string value = parameterElement.Attribute("Name").Value;
// ReSharper restore PossibleNullReferenceException
                    FormalParameters.Add(value, parameterElement.Value);
                }
            }
        }

        public string XmlFor()
        {
            StringWriter swrtr = new StringWriter();
            XmlTextWriter xwrtr = new XmlTextWriter(swrtr);
            XmlFor(xwrtr, true);
            return swrtr.ToString();
        }

        public abstract void Execute(IDataPacketType data);

        public abstract bool Check(IDataPacketType data);

        public abstract void ResolveName(string qualifiedName);

        public abstract void XmlFor(XmlWriter xwrtr, bool writeNamespaceAttribute);

        public abstract BaseActionType Copy();

        public abstract string ToString(string indent);
    }
    public enum ActionOriginType
    {
        FromPropertyType,
        FromCurrentType
    }
}

